import copy

import pymysql
import pytest

from configs import setting


class AssertUtil:

    # 数据库断言
    # 连接数据库
    def conn_database(self):
        self.conn = pymysql.connect(
            user = setting.db_user,
            password = setting.db_password,
            host = setting.db_host,
            database = setting.db_database,
            port = setting.db_port
        )
        return self.conn

    # 执行SQL
    def excute_sql(self,sql):
        # 创建数据库连接
        conn = self.conn_database()
        # 创建游标
        cursor = conn.cursor()
        # 执行SQL
        cursor.execute(sql)
        # 取值
        value = cursor.fetchone()
        # 关闭资源
        cursor.close()
        conn.close()
        # 返回值
        return value


    def assert_all_case(self,res,assert_type,value):
        # 1.深拷贝一个res
        new_res = copy.deepcopy(res)
        # 2.把json方法改成json属性
        try:
            new_res.json = new_res.json()
        except Exception:
            new_res.json = {"msg": "response not json data"}
        # 3.循环判断断言
        for msg,expect_and_real_data in value.items():
            expect,real = expect_and_real_data[0],expect_and_real_data[1]
            print(assert_type,msg,expect,real)
            # 判断断言
            try:
                real_value = getattr(new_res, real)
                # 这行代码尝试从 new_res 对象中获取名称为 real 变量值的属性，并把获取到的值赋给 real_value 变量。
            except Exception:
                # 非字符串类型，直接赋值
                real_value = real
            print("++++++++real_value++++++", real_value)
            # 判断断言类型
            match assert_type:
                case "equals":
                    assert real_value == expect, f"{msg} 失败: 预期 {expect}, 实际 {real_value}"

                case "db_equals" | "db_contains":
                    # 数据库断言：执行SQL查询并比较结果
                    db_result = self.excute_sql(expect)
                    if not db_result:
                        pytest.fail(f"数据库查询无结果: {expect}")

                    # 获取数据库查询结果
                    db_value = db_result[0]
                    print("++++++++db_value++++++", db_value)

                    # 根据real的类型决定比较方式
                    if isinstance(real, str):
                        assert db_value in real_value.values(), f"{msg} 失败: 预期 {db_value} 在 {real_value.values()} 里面，实际不在"
                    else:
                        # 如果real是整数/浮点数，直接比较数据库值与预期值
                        assert db_value == real, f"{msg} 失败: 预期 {db_value}, 实际 {real}"

                case "contains":
                    # 包含断言
                    assert expect in real_value, f"{msg} 失败: 预期 {expect} 在 {real_value} 里面，实际不在"
